use rocket::{
    fairing::{self, Fairing, Info, Kind},
    http::Header,
    Build, Config, Request, Response, Rocket,
};
use tokio::sync::RwLock;

pub struct Cors;

static CORS_ORIGIN: RwLock<Option<String>> = RwLock::const_new(None);

#[rocket::async_trait]
impl Fairing for Cors {
    fn info(&self) -> Info {
        Info {
            name: "CORS Header",
            kind: Kind::Ignite | Kind::Response | Kind::Singleton,
        }
    }

    async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {
        let cors_origin = Config::figment().find_value("origin");
        let cors_origin = match cors_origin {
            Ok(cors_origin) => cors_origin,
            Err(_) => return fairing::Result::Ok(rocket),
        };
        let cors_origin = match cors_origin.as_str() {
            Some(cors_origin) => cors_origin,
            None => return fairing::Result::Ok(rocket),
        };
        println!("CORS origin: {}", cors_origin);

        let mut lock = CORS_ORIGIN.write().await;
        *lock = Some(cors_origin.to_string());

        fairing::Result::Ok(rocket)
    }

    async fn on_response<'r>(&self, _: &'r Request<'_>, response: &mut Response<'r>) {
        let cors_origin = CORS_ORIGIN.read().await;
        if let Some(cors_origin) = &*cors_origin {
            let cors_origin = cors_origin.clone();
            response.set_header(Header::new("Access-Control-Allow-Origin", cors_origin));
        }
    }
}
